/*****************************************************************************
 Copyright (c) 2018-2021, Intel Corporation

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

     * Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of Intel Corporation nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <intel-ipsec-mb.h>
#include "gcm_ctr_vectors_test.h"
#include "utils.h"

enum cmac_type {
        CMAC_128 = 0,
        CMAC_128_BITLEN,
        CMAC_256,
};

int cmac_test(struct IMB_MGR *mb_mgr);

/*
 * Test vectors from https://tools.ietf.org/html/rfc4493
 */

/*
 *  Subkey Generation
 *  K              2b7e1516 28aed2a6 abf71588 09cf4f3c
 *  AES-128(key,0) 7df76b0c 1ab899b3 3e42f047 b91b546f
 *  K1             fbeed618 35713366 7c85e08f 7236a8de
 *  K2             f7ddac30 6ae266cc f90bc11e e46d513b
 */
static const uint8_t key[16] = {
        0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
static const uint8_t sub_key1[16] = {
        0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
        0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
};
static const uint8_t sub_key2[16] = {
        0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
        0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
};

/*
 *  Example 1: len = 0
 *  M              <empty string>
 *  AES-CMAC       bb1d6929 e9593728 7fa37d12 9b756746
 */
static const uint8_t T_1[16] = {
        0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
        0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
};

/*
 *  Example 2: len = 16
 *  M              6bc1bee2 2e409f96 e93d7e11 7393172a
 *  AES-CMAC       070a16b4 6b4d4144 f79bdd9d d04a287c
 */
static const uint8_t T_2[16] = {
        0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
        0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
};

/*
 *  Example 3: len = 40
 *  M              6bc1bee2 2e409f96 e93d7e11 7393172a
 *                 ae2d8a57 1e03ac9c 9eb76fac 45af8e51
 *                 30c81c46 a35ce411
 *  AES-CMAC       dfa66747 de9ae630 30ca3261 1497c827
 */
static const uint8_t T_3[16] = {
        0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
        0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
};

/*
 *  Example 4: len = 64
 *  M              6bc1bee2 2e409f96 e93d7e11 7393172a
 *                 ae2d8a57 1e03ac9c 9eb76fac 45af8e51
 *                 30c81c46 a35ce411 e5fbc119 1a0a52ef
 *                 f69f2445 df4f9b17 ad2b417b e66c3710
 *  AES-CMAC       51f0bebf 7e3b9d92 fc497417 79363cfe
 */
static const uint8_t T_4[16] = {
        0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
        0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
};

/*
 *  Custom Vector
 *
 *  Example 5: len = 8
 *  M              6bc1bee2 2e409f96
 *  AES-CMAC       dc87cdcf 77a2f182 9e012c4d 31af2f8b
 */
static const uint8_t T_5[16] = {
        0xdc, 0x87, 0xcd, 0xcf, 0x77, 0xa2, 0xf1, 0x82,
        0x9e, 0x01, 0x2c, 0x4d, 0x31, 0xaf, 0x2f, 0x8b
};

static const uint8_t M[64] = {
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
        0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
        0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
        0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
        0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
        0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
        0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
};

/*
 * 3GPP 33.401 C.2.1 Test Case 1
 *
 * CMAC(K,M):
 *   K         = (hex) 2bd6459f 82c5b300 952c4910 4881ff48
 *   Mlen      = 122 (bits)
 *   M         = (hex) 38a6f056 c0000000 33323462 63393840
 *
 * Subkey generation:
 *   K1        = (hex) dc84c270 b5bf83f9 6f90be18 8d3f6418
 *   K2        = (hex) b90984e1 6b7f07f2 df217c31 1a7ec8b7
 *
 * MAC generation:
 *   C1        = (hex) 118c6eb8 b775144b 0b831110 54c96eb6
 *   MACT      = (hex) 118c6eb8
 */
static const uint8_t EIA2_128_K_1[16] = {
        0x2b, 0xd6, 0x45, 0x9f, 0x82, 0xc5, 0xb3, 0x00,
        0x95, 0x2c, 0x49, 0x10, 0x48, 0x81, 0xff, 0x48
};

static const uint8_t EIA2_128_SK1_1[16] = {
        0xdc, 0x84, 0xc2, 0x70, 0xb5, 0xbf, 0x83, 0xf9,
        0x6f, 0x90, 0xbe, 0x18, 0x8d, 0x3f, 0x64, 0x18
};

static const uint8_t EIA2_128_SK2_1[16] = {
        0xb9, 0x09, 0x84, 0xe1, 0x6b, 0x7f, 0x07, 0xf2,
        0xdf, 0x21, 0x7c, 0x31, 0x1a, 0x7e, 0xc8, 0xb7
};

static const uint8_t EIA2_128_T_1[4] = {
        0x11, 0x8c, 0x6e, 0xb8
};

static const uint8_t EIA2_128_M_1[16] = {
        0x38, 0xa6, 0xf0, 0x56, 0xc0, 0x00, 0x00, 0x00,
        0x33, 0x32, 0x34, 0x62, 0x63, 0x39, 0x38, 0x40 /* 0x40 = 0100 0000 */
};

/*
 * 3GPP 33.401 C.2.1 Test Case 2
 *
 * CMAC(K, M):
 *   K         = d3c5d592 327fb11c 4035c668 0af8c6d1
 *   Mlen      = 128
 *   M         = 398a59b4 d4000000 484583d5 afe082ae
 *
 * Subkey Generation:
 *   L         = 9b71f299 132915d3 605211b5 e5df8632
 *   K1        = 36e3e532 26522ba6 c0a4236b cbbf0ce3
 *   K2        = 6dc7ca64 4ca4574d 814846d7 977e19c6
 *
 * MAC generation:
 *   C1        = b93787e6 493ff113 ad73d3e0 1e826d73
 *   MACT      = b93787e6
 */
static const uint8_t EIA2_128_K_2[16] = {
        0xd3, 0xc5, 0xd5, 0x92, 0x32, 0x7f, 0xb1, 0x1c,
        0x40, 0x35, 0xc6, 0x68, 0x0a, 0xf8, 0xc6, 0xd1
};

static const uint8_t EIA2_128_SK1_2[16] = {
        0x36, 0xe3, 0xe5, 0x32, 0x26, 0x52, 0x2b, 0xa6,
        0xc0, 0xa4, 0x23, 0x6b, 0xcb, 0xbf, 0x0c, 0xe3
};

static const uint8_t EIA2_128_SK2_2[16] = {
        0x6d, 0xc7, 0xca, 0x64, 0x4c, 0xa4, 0x57, 0x4d,
        0x81, 0x48, 0x46, 0xd7, 0x97, 0x7e, 0x19, 0xc6
};

static const uint8_t EIA2_128_T_2[4] = {
        0xb9, 0x37, 0x87, 0xe6
};

static const uint8_t EIA2_128_M_2[16] = {
        0x39, 0x8a, 0x59, 0xb4, 0xd4, 0x00, 0x00, 0x00,
        0x48, 0x45, 0x83, 0xd5, 0xaf, 0xe0, 0x82, 0xae
};

/*
 * 3GPP 33.401 C.2.1 Test Case 3
 *
 * CMAC(K, M):
 *   K         = 7e5e9443 1e11d738 28d739cc 6ced4573
 *   Mlen      = 318
 *   M         = 36af6144 c4000000 b3d3c917 0a4e1632 f60f8610 13d22d84 b726b6a2
 *               78d802d1 eeaf1321 ba5929dc
 *
 * Subkey Generation:
 *   L         = d78b4628 35781e79 d2255f8d 309a60ef
 *   K1        = af168c50 6af03cf3 a44abf1a 6134c159
 *   K2        = 5e2d18a0 d5e079e7 48957e34 c2698235
 *
 * MAC generation:
 *   C3        = 1f60b01d e05aa666 3bda32c6 1771e70b
 *   MACT      = 1f60b01d
 */
static const uint8_t EIA2_128_K_3[16] = {
        0x7e, 0x5e, 0x94, 0x43, 0x1e, 0x11, 0xd7, 0x38,
        0x28, 0xd7, 0x39, 0xcc, 0x6c, 0xed, 0x45, 0x73
};

static const uint8_t EIA2_128_SK1_3[16] = {
        0xaf, 0x16, 0x8c, 0x50, 0x6a, 0xf0, 0x3c, 0xf3,
        0xa4, 0x4a, 0xbf, 0x1a, 0x61, 0x34, 0xc1, 0x59
};

static const uint8_t EIA2_128_SK2_3[16] = {
        0x5e, 0x2d, 0x18, 0xa0, 0xd5, 0xe0, 0x79, 0xe7,
        0x48, 0x95, 0x7e, 0x34, 0xc2, 0x69, 0x82, 0x35
};

static const uint8_t EIA2_128_T_3[4] = {
        0x1f, 0x60, 0xb0, 0x1d
};

static const uint8_t EIA2_128_M_3[40] = {
        0x36, 0xaf, 0x61, 0x44, 0xc4, 0x00, 0x00, 0x00,
        0xb3, 0xd3, 0xc9, 0x17, 0x0a, 0x4e, 0x16, 0x32,
        0xf6, 0x0f, 0x86, 0x10, 0x13, 0xd2, 0x2d, 0x84,
        0xb7, 0x26, 0xb6, 0xa2, 0x78, 0xd8, 0x02, 0xd1,
        0xee, 0xaf, 0x13, 0x21, 0xba, 0x59, 0x29, 0xdc
};

/*
 * 3GPP 33.401 C.2.1 Test Case 4
 *
 * CMAC(K, M):
 *   K         = d3419be8 21087acd 02123a92 48033359
 *   Mlen      = 575
 *   M         = c7590ea9 b8000000 bbb05703 8809496b
 *               cff86d6f bc8ce5b1 35a06b16 6054f2d5
 *               65be8ace 75dc851e 0bcdd8f0 7141c495
 *               872fb5d8 c0c66a8b 6da55666 3e4e4612
 *               05d84580 bee5bc7e
 *
 * Subkey Generation:
 *   L         = 054dd008 2d9ecd21 a3f32b0a a7369be4
 *   K1        = 0a9ba010 5b3d9a43 47e65615 4e6d37c8
 *   K2        = 15374020 b67b3486 8fccac2a 9cda6f90
 *
 * MAC generation:
 *   C5        = 6846a2f0 a0b6be7a 4fb26a15 7e914c53
 *   MACT      = 6846a2f0
 */
static const uint8_t EIA2_128_K_4[16] = {
        0xd3, 0x41, 0x9b, 0xe8, 0x21, 0x08, 0x7a, 0xcd,
        0x02, 0x12, 0x3a, 0x92, 0x48, 0x03, 0x33, 0x59
};

static const uint8_t EIA2_128_SK1_4[16] = {
        0x0a, 0x9b, 0xa0, 0x10, 0x5b, 0x3d, 0x9a, 0x43,
        0x47, 0xe6, 0x56, 0x15, 0x4e, 0x6d, 0x37, 0xc8
};

static const uint8_t EIA2_128_SK2_4[16] = {
        0x15, 0x37, 0x40, 0x20, 0xb6, 0x7b, 0x34, 0x86,
        0x8f, 0xcc, 0xac, 0x2a, 0x9c, 0xda, 0x6f, 0x90
};

static const uint8_t EIA2_128_T_4[4] = {
        0x68, 0x46, 0xa2, 0xf0
};

static const uint8_t EIA2_128_M_4[72] = {
        0xc7, 0x59, 0x0e, 0xa9, 0xb8, 0x00, 0x00, 0x00,
        0xbb, 0xb0, 0x57, 0x03, 0x88, 0x09, 0x49, 0x6b,
        0xcf, 0xf8, 0x6d, 0x6f, 0xbc, 0x8c, 0xe5, 0xb1,
        0x35, 0xa0, 0x6b, 0x16, 0x60, 0x54, 0xf2, 0xd5,
        0x65, 0xbe, 0x8a, 0xce, 0x75, 0xdc, 0x85, 0x1e,
        0x0b, 0xcd, 0xd8, 0xf0, 0x71, 0x41, 0xc4, 0x95,
        0x87, 0x2f, 0xb5, 0xd8, 0xc0, 0xc6, 0x6a, 0x8b,
        0x6d, 0xa5, 0x56, 0x66, 0x3e, 0x4e, 0x46, 0x12,
        0x05, 0xd8, 0x45, 0x80, 0xbe, 0xe5, 0xbc, 0x7e
};

/*
 * 3GPP 33.401 C.2.1 Test Case 5
 *
 * CMAC(K, M):
 *   K         = 83fd23a2 44a74cf3 58da3019 f1722635
 *   Mlen      = 832
 *   M         = 36af6144 7c000000 35c68716 633c66fb
 *               750c2668 65d53c11 ea05b1e9 fa49c839
 *               8d48e1ef a5909d39 47902837 f5ae96d5
 *               a05bc8d6 1ca8dbef 1b13a4b4 abfe4fb1
 *               006045b6 74bb5472 9304c382 be53a5af
 *               05556176 f6eaa2ef 1d05e4b0 83181ee6
 *               74cda5a4 85f74d7a
 *
 * Subkey Generation:
 *   L         = 9df61c57 3c86acac 704db9d5 b0dea444
 *   K1        = 3bec38ae 790d5958 e09b73ab 61bd480f
 *   K2        = 77d8715c f21ab2b1 c136e756 c37a901e
 *
 * MAC generation:
 *   C7        = e657e182 5298f2fa ee2ca1e0 7373bc7e
 *   MACT      = e657e182
 */
static const uint8_t EIA2_128_K_5[16] = {
        0x83, 0xfd, 0x23, 0xa2, 0x44, 0xa7, 0x4c, 0xf3,
        0x58, 0xda, 0x30, 0x19, 0xf1, 0x72, 0x26, 0x35
};

static const uint8_t EIA2_128_SK1_5[16] = {
        0x3b, 0xec, 0x38, 0xae, 0x79, 0x0d, 0x59, 0x58,
        0xe0, 0x9b, 0x73, 0xab, 0x61, 0xbd, 0x48, 0x0f
};

static const uint8_t EIA2_128_SK2_5[16] = {
        0x77, 0xd8, 0x71, 0x5c, 0xf2, 0x1a, 0xb2, 0xb1,
        0xc1, 0x36, 0xe7, 0x56, 0xc3, 0x7a, 0x90, 0x1e
};

static const uint8_t EIA2_128_T_5[4] = {
        0xe6, 0x57, 0xe1, 0x82
};

static const uint8_t EIA2_128_M_5[104] = {
        0x36, 0xaf, 0x61, 0x44, 0x7c, 0x00, 0x00, 0x00,
        0x35, 0xc6, 0x87, 0x16, 0x63, 0x3c, 0x66, 0xfb,
        0x75, 0x0c, 0x26, 0x68, 0x65, 0xd5, 0x3c, 0x11,
        0xea, 0x05, 0xb1, 0xe9, 0xfa, 0x49, 0xc8, 0x39,
        0x8d, 0x48, 0xe1, 0xef, 0xa5, 0x90, 0x9d, 0x39,
        0x47, 0x90, 0x28, 0x37, 0xf5, 0xae, 0x96, 0xd5,
        0xa0, 0x5b, 0xc8, 0xd6, 0x1c, 0xa8, 0xdb, 0xef,
        0x1b, 0x13, 0xa4, 0xb4, 0xab, 0xfe, 0x4f, 0xb1,
        0x00, 0x60, 0x45, 0xb6, 0x74, 0xbb, 0x54, 0x72,
        0x93, 0x04, 0xc3, 0x82, 0xbe, 0x53, 0xa5, 0xaf,
        0x05, 0x55, 0x61, 0x76, 0xf6, 0xea, 0xa2, 0xef,
        0x1d, 0x05, 0xe4, 0xb0, 0x83, 0x18, 0x1e, 0xe6,
        0x74, 0xcd, 0xa5, 0xa4, 0x85, 0xf7, 0x4d, 0x7a
};

/*
 * 3GPP 33.401 C.2.1 Test Case 6
 *
 * CMAC(K, M):
 *   K         = 6832a65c ff447362 1ebdd4ba 26a921fe
 *   Mlen      = 447
 *   M         = 36af6144 c0000000 d3c53839 62682071
 *               77656676 20323837 63624098 1ba6824c
 *               1bfb1ab4 85472029 b71d808c e33e2cc3
 *               c0b5fc1f 3de8a6dc
 *
 * Subkey Generation:
 *   L         = e50123c3 87e13fd6 8d8bf0d0 a4581685
 *   K1        = ca024787 0fc27fad 1b17e1a1 48b02d8d
 *   K2        = 94048f0e 1f84ff5a 362fc342 91605b9d
 *
 * MAC generation:
 *   C4        = f0668c1e 4197300b 1243f834 25d06c25
 *   MACT      = f0668c1e
 */
static const uint8_t EIA2_128_K_6[16] = {
        0x68, 0x32, 0xa6, 0x5c, 0xff, 0x44, 0x73, 0x62,
        0x1e, 0xbd, 0xd4, 0xba, 0x26, 0xa9, 0x21, 0xfe
};

static const uint8_t EIA2_128_SK1_6[16] = {
        0xca, 0x02, 0x47, 0x87, 0x0f, 0xc2, 0x7f, 0xad,
        0x1b, 0x17, 0xe1, 0xa1, 0x48, 0xb0, 0x2d, 0x8d
};

static const uint8_t EIA2_128_SK2_6[16] = {
        0x94, 0x04, 0x8f, 0x0e, 0x1f, 0x84, 0xff, 0x5a,
        0x36, 0x2f, 0xc3, 0x42, 0x91, 0x60, 0x5b, 0x9d
};

static const uint8_t EIA2_128_T_6[4] = {
        0xf0, 0x66, 0x8c, 0x1e
};

static const uint8_t EIA2_128_M_6[56] = {
        0x36, 0xaf, 0x61, 0x44, 0xc0, 0x00, 0x00, 0x00,
        0xd3, 0xc5, 0x38, 0x39, 0x62, 0x68, 0x20, 0x71,
        0x77, 0x65, 0x66, 0x76, 0x20, 0x32, 0x38, 0x37,
        0x63, 0x62, 0x40, 0x98, 0x1b, 0xa6, 0x82, 0x4c,
        0x1b, 0xfb, 0x1a, 0xb4, 0x85, 0x47, 0x20, 0x29,
        0xb7, 0x1d, 0x80, 0x8c, 0xe3, 0x3e, 0x2c, 0xc3,
        0xc0, 0xb5, 0xfc, 0x1f, 0x3d, 0xe8, 0xa6, 0xdc
};

/*
 * 3GPP 33.401 C.2.1 Test Case 7
 *
 * CMAC(K, M):
 *   K         = 5d0a80d8 134ae196 77824b67 1e838af4
 *   Mlen      = 2622
 *   M         = 7827fab2 2c000000 70dedf2d c42c5cbd
 *               3a96f8a0 b11418b3 608d5733 604a2cd3
 *               6aabc70c e3193bb5 153be2d3 c06dfdb2
 *               d16e9c35 7158be6a 41d6b861 e491db3f
 *               bfeb518e fcf048d7 d5895373 0ff30c9e
 *               c470ffcd 663dc342 01c36add c0111c35
 *               b38afee7 cfdb582e 3731f8b4 baa8d1a8
 *               9c06e811 99a97162 27be344e fcb436dd
 *               d0f096c0 64c3b5e2 c399993f c77394f9
 *               e09720a8 11850ef2 3b2ee05d 9e617360
 *               9d86e1c0 c18ea51a 012a00bb 413b9cb8
 *               188a703c d6bae31c c67b34b1 b00019e6
 *               a2b2a690 f02671fe 7c9ef8de c0094e53
 *               3763478d 58d2c5f5 b827a014 8c5948a9
 *               6931acf8 4f465a64 e62ce740 07e991e3
 *               7ea823fa 0fb21923 b79905b7 33b631e6
 *               c7d6860a 3831ac35 1a9c730c 52ff72d9
 *               d308eedb ab21fde1 43a0ea17 e23edc1f
 *               74cbb363 8a2033aa a15464ea a733385d
 *               bbeb6fd7 3509b857 e6a419dc a1d8907a
 *               f977fbac 4dfa35ec
 *
 * Subkey Generation:
 *   L         = 9832e229 fbb93970 bcf7b282 3ee4fe5d
 *   K1        = 3065c453 f77272e1 79ef6504 7dc9fc3d
 *   K2        = 60cb88a7 eee4e5c2 f3deca08 fb93f87a
 *
 * MAC generation:
 *   C21       = f4cc8fa3 59e6e2e7 6e09c45d 6ea5e0de
 *   MACT      = f4cc8fa3
 */
static const uint8_t EIA2_128_K_7[16] = {
        0x5d, 0x0a, 0x80, 0xd8, 0x13, 0x4a, 0xe1, 0x96,
        0x77, 0x82, 0x4b, 0x67, 0x1e, 0x83, 0x8a, 0xf4
};

static const uint8_t EIA2_128_SK1_7[16] = {
        0x30, 0x65, 0xc4, 0x53, 0xf7, 0x72, 0x72, 0xe1,
        0x79, 0xef, 0x65, 0x04, 0x7d, 0xc9, 0xfc, 0x3d
};

static const uint8_t EIA2_128_SK2_7[16] = {
        0x60, 0xcb, 0x88, 0xa7, 0xee, 0xe4, 0xe5, 0xc2,
        0xf3, 0xde, 0xca, 0x08, 0xfb, 0x93, 0xf8, 0x7a
};

static const uint8_t EIA2_128_T_7[4] = {
        0xf4, 0xcc, 0x8f, 0xa3
};

static const uint8_t EIA2_128_M_7[328] = {
        0x78, 0x27, 0xfa, 0xb2, 0x2c, 0x00, 0x00, 0x00,
        0x70, 0xde, 0xdf, 0x2d, 0xc4, 0x2c, 0x5c, 0xbd,
        0x3a, 0x96, 0xf8, 0xa0, 0xb1, 0x14, 0x18, 0xb3,
        0x60, 0x8d, 0x57, 0x33, 0x60, 0x4a, 0x2c, 0xd3,
        0x6a, 0xab, 0xc7, 0x0c, 0xe3, 0x19, 0x3b, 0xb5,
        0x15, 0x3b, 0xe2, 0xd3, 0xc0, 0x6d, 0xfd, 0xb2,
        0xd1, 0x6e, 0x9c, 0x35, 0x71, 0x58, 0xbe, 0x6a,
        0x41, 0xd6, 0xb8, 0x61, 0xe4, 0x91, 0xdb, 0x3f,
        0xbf, 0xeb, 0x51, 0x8e, 0xfc, 0xf0, 0x48, 0xd7,
        0xd5, 0x89, 0x53, 0x73, 0x0f, 0xf3, 0x0c, 0x9e,
        0xc4, 0x70, 0xff, 0xcd, 0x66, 0x3d, 0xc3, 0x42,
        0x01, 0xc3, 0x6a, 0xdd, 0xc0, 0x11, 0x1c, 0x35,
        0xb3, 0x8a, 0xfe, 0xe7, 0xcf, 0xdb, 0x58, 0x2e,
        0x37, 0x31, 0xf8, 0xb4, 0xba, 0xa8, 0xd1, 0xa8,
        0x9c, 0x06, 0xe8, 0x11, 0x99, 0xa9, 0x71, 0x62,
        0x27, 0xbe, 0x34, 0x4e, 0xfc, 0xb4, 0x36, 0xdd,
        0xd0, 0xf0, 0x96, 0xc0, 0x64, 0xc3, 0xb5, 0xe2,
        0xc3, 0x99, 0x99, 0x3f, 0xc7, 0x73, 0x94, 0xf9,
        0xe0, 0x97, 0x20, 0xa8, 0x11, 0x85, 0x0e, 0xf2,
        0x3b, 0x2e, 0xe0, 0x5d, 0x9e, 0x61, 0x73, 0x60,
        0x9d, 0x86, 0xe1, 0xc0, 0xc1, 0x8e, 0xa5, 0x1a,
        0x01, 0x2a, 0x00, 0xbb, 0x41, 0x3b, 0x9c, 0xb8,
        0x18, 0x8a, 0x70, 0x3c, 0xd6, 0xba, 0xe3, 0x1c,
        0xc6, 0x7b, 0x34, 0xb1, 0xb0, 0x00, 0x19, 0xe6,
        0xa2, 0xb2, 0xa6, 0x90, 0xf0, 0x26, 0x71, 0xfe,
        0x7c, 0x9e, 0xf8, 0xde, 0xc0, 0x09, 0x4e, 0x53,
        0x37, 0x63, 0x47, 0x8d, 0x58, 0xd2, 0xc5, 0xf5,
        0xb8, 0x27, 0xa0, 0x14, 0x8c, 0x59, 0x48, 0xa9,
        0x69, 0x31, 0xac, 0xf8, 0x4f, 0x46, 0x5a, 0x64,
        0xe6, 0x2c, 0xe7, 0x40, 0x07, 0xe9, 0x91, 0xe3,
        0x7e, 0xa8, 0x23, 0xfa, 0x0f, 0xb2, 0x19, 0x23,
        0xb7, 0x99, 0x05, 0xb7, 0x33, 0xb6, 0x31, 0xe6,
        0xc7, 0xd6, 0x86, 0x0a, 0x38, 0x31, 0xac, 0x35,
        0x1a, 0x9c, 0x73, 0x0c, 0x52, 0xff, 0x72, 0xd9,
        0xd3, 0x08, 0xee, 0xdb, 0xab, 0x21, 0xfd, 0xe1,
        0x43, 0xa0, 0xea, 0x17, 0xe2, 0x3e, 0xdc, 0x1f,
        0x74, 0xcb, 0xb3, 0x63, 0x8a, 0x20, 0x33, 0xaa,
        0xa1, 0x54, 0x64, 0xea, 0xa7, 0x33, 0x38, 0x5d,
        0xbb, 0xeb, 0x6f, 0xd7, 0x35, 0x09, 0xb8, 0x57,
        0xe6, 0xa4, 0x19, 0xdc, 0xa1, 0xd8, 0x90, 0x7a,
        0xf9, 0x77, 0xfb, 0xac, 0x4d, 0xfa, 0x35, 0xec
};

/*
 * 3GPP 33.401 C.2.1 Test Case 8
 *
 * CMAC(K, M):
 *   K         = b3120ffd b2cf6af4 e73eaf2e f4ebec69
 *   Mlen      = 16512
 *   M         = 296f393c 5c000000 00000000 00000000
 *               01010101 01010101 e0958045 f3a0bba4
 *               e3968346 f0a3b8a7 c02a018a e6407652
 *               26b987c9 13e6cbf0 83570016 cf83efbc
 *               61c08251 3e21561a 427c009d 28c298ef
 *               ace78ed6 d56c2d45 05ad032e 9c04dc60
 *               e73a8169 6da665c6 c48603a5 7b45ab33
 *               221585e6 8ee31691 87fb0239 528632dd
 *               656c807e a3248b7b 46d002b2 b5c7458e
 *               b85b9ce9 5879e034 0859055e 3b0abbc3
 *               eace8719 caa80265 c97205d5 dc4bcc90
 *               2fe18396 29ed7132 8a0f0449 f588557e
 *               6898860e 042aecd8 4b2404c2 12c9222d
 *               a5bf8a89 ef679787 0cf50771 a60f66a2
 *               ee628536 57addf04 cdde07fa 414e11f1
 *               2b4d81b9 b4e8ac53 8ea30666 688d881f
 *               6c348421 992f31b9 4f8806ed 8fccff4c
 *               9123b896 42527ad6 13b109bf 75167485
 *               f1268bf8 84b4cd23 d29a0934 925703d6
 *               34098f77 67f1be74 91e708a8 bb949a38
 *               73708aef 4a36239e 50cc0823 5cd5ed6b
 *               be578668 a17b58c1 171d0b90 e813a9e4
 *               f58a89d7 19b11042 d6360b1b 0f52deb7
 *               30a58d58 faf46315 954b0a87 26914759
 *               77dc88c0 d733feff 54600a0c c1d0300a
 *               aaeb9457 2c6e95b0 1ae90de0 4f1dce47
 *               f87e8fa7 bebf77e1 dbc20d6b a85cb914
 *               3d518b28 5dfa04b6 98bf0cf7 819f20fa
 *               7a288eb0 703d995c 59940c7c 66de57a9
 *               b70f8237 9b70e203 1e450fcf d2181326
 *               fcd28d88 23baaa80 df6e0f44 35596475
 *               39fd8907 c0ffd9d7 9c130ed8 1c9afd9b
 *               7e848c9f ed38443d 5d380e53 fbdb8ac8
 *               c3d3f068 76054f12 2461107d e92fea09
 *               c6f6923a 188d53af e54a10f6 0e6e9d5a
 *               03d996b5 fbc820f8 a637116a 27ad04b4
 *               44a0932d d60fbd12 671c11e1 c0ec73e7
 *               89879faa 3d42c64d 20cd1252 742a3768
 *               c25a9015 85888ece e1e612d9 936b403b
 *               0775949a 66cdfd99 a29b1345 baa8d9d5
 *               400c9102 4b0a6073 63b013ce 5de9ae86
 *               9d3b8d95 b0570b3c 2d391422 d32450cb
 *               cfae9665 2286e96d ec1214a9 34652798
 *               0a8192ea c1c39a3a af6f1535 1da6be76
 *               4df89772 ec0407d0 6e4415be fae7c925
 *               80df9bf5 07497c8f 2995160d 4e218daa
 *               cb02944a bf83340c e8be1686 a960faf9
 *               0e2d90c5 5cc6475b abc3171a 80a36317
 *               4954955d 7101dab1 6ae81791 67e21444
 *               b443a9ea aa7c91de 36d118c3 9d389f8d
 *               d4469a84 6c9a262b f7fa1848 7a79e8de
 *               11699e0b 8fdf557c b48719d4 53ba7130
 *               56109b93 a218c896 75ac195f b4fb0663
 *               9b379714 4955b3c9 327d1aec 003d42ec
 *               d0ea98ab f19ffb4a f3561a67 e77c35bf
 *               15c59c24 12da881d b02b1bfb cebfac51
 *               52bc99bc 3f1d15f7 71001b70 29fedb02
 *               8f8b852b c4407eb8 3f891c9c a733254f
 *               dd1e9edb 56919ce9 fea21c17 4072521c
 *               18319a54 b5d4efbe bddf1d8b 69b1cbf2
 *               5f489fcc 98137254 7cf41d00 8ef0bca1
 *               926f934b 735e090b 3b251eb3 3a36f82e
 *               d9b29cf4 cb944188 fa0e1e38 dd778f7d
 *               1c9d987b 28d132df b9731fa4 f4b41693
 *               5be49de3 0516af35 78581f2f 13f561c0
 *               66336194 1eab249a 4bc123f8 d15cd711
 *               a956a1bf 20fe6eb7 8aea2373 361da042
 *               6c79a530 c3bb1de0 c99722ef 1fde39ac
 *               2b00a0a8 ee7c800a 08bc2264 f89f4eff
 *               e627ac2f 0531fb55 4f6d21d7 4c590a70
 *               adfaa390 bdfbb3d6 8e46215c ab187d23
 *               68d5a71f 5ebec081 cd3b20c0 82dbe4cd
 *               2faca287 73795d6b 0c10204b 659a939e
 *               f29bbe10 88243624 429927a7 eb576dd3
 *               a00ea5e0 1af5d475 83b2272c 0c161a80
 *               6521a16f f9b0a722 c0cf26b0 25d5836e
 *               2258a4f7 d4773ac8 01e4263b c294f43d
 *               ef7fa870 3f3a4197 46352588 7652b0b2
 *               a4a2a7cf 87f00914 871e2503 9113c7e1
 *               618da340 64b57a43 c463249f b8d05e0f
 *               26f4a6d8 4972e7a9 05482414 5f91295c
 *               dbe39a6f 920facc6 59712b46 a54ba295
 *               bbe6a901 54e91b33 985a2bcd 420ad5c6
 *               7ec9ad8e b7ac6864 db272a51 6bc94c28
 *               39b0a816 9a6bf58e 1a0c2ada 8c883b7b
 *               f497a491 71268ed1 5ddd2969 384e7ff4
 *               bf4aab2e c9ecc652 9cf629e2 df0f08a7
 *               7a65afa1 2aa9b505 df8b287e f6cc9149
 *               3d1caa39 076e28ef 1ea028f5 118de61a
 *               e02bb6ae fc3343a0 50292f19 9f401857
 *               b2bead5e 6ee2a1f1 91022f92 78016f04
 *               7791a9d1 8da7d2a6 d27f2e0e 51c2f6ea
 *               30e8ac49 a0604f4c 13542e85 b68381b9
 *               fdcfa0ce 4b2d3413 54852d36 0245c536
 *               b612af71 f3e77c90 95ae2dbd e504b265
 *               733dabfe 10a20fc7 d6d32c21 ccc72b8b
 *               3444ae66 3d65922d 17f82caa 2b865cd8
 *               8913d291 a6589902 6ea13284 39723c19
 *               8c36b0c3 c8d085bf af8a320f de334b4a
 *               4919b44c 2b95f6e8 ecf73393 f7f0d2a4
 *               0e60b1d4 06526b02 2ddc3318 10b1a5f7
 *               c347bd53 ed1f105d 6a0d30ab a477e178
 *               889ab2ec 55d558de ab263020 4336962b
 *               4db5b663 b6902b89 e85b31bc 6af50fc5
 *               0accb3fb 9b57b663 29703137 8db47896
 *               d7fbaf6c 600add2c 67f936db 037986db
 *               856eb49c f2db3f7d a6d23650 e438f188
 *               4041b013 119e4c2a e5af37cc cdfb6866
 *               0738b58b 3c59d1c0 24843747 2aba1f35
 *               ca1fb90c d714aa9f 635534f4 9e7c5bba
 *               81c2b6b3 6fdee21c a27e347f 793d2ce9
 *               44edb23c 8c9b914b e10335e3 50feb507
 *               0394b7a4 a15c0ca1 20283568 b7bfc254
 *               fe838b13 7a2147ce 7c113a3a 4d65499d
 *               9e86b87d bcc7f03b bd3a3ab1 aa243ece
 *               5ba9bcf2 5f82836c fe473b2d 83e7a720
 *               1cd0b96a 72451e86 3f6c3ba6 64a6d073
 *               d1f7b5ed 990865d9 78bd3815 d06094fc
 *               9a2aba52 21c22d5a b996389e 3721e3af
 *               5f05bedd c2875e0d faeb3902 1ee27a41
 *               187cbb45 ef40c3e7 3bc03989 f9a30d12
 *               c54ba7d2 141da8a8 75493e65 776ef35f
 *               97debc22 86cc4af9 b4623eee 902f840c
 *               52f1b8ad 658939ae f71f3f72 b9ec1de2
 *               1588bd35 484ea444 36343ff9 5ead6ab1
 *               d8afb1b2 a303df1b 71e53c4a ea6b2e3e
 *               9372be0d 1bc99798 b0ce3cc1 0d2a596d
 *               565dba82 f88ce4cf f3b33d5d 24e9c083
 *               1124bf1a d54b7925 32983dd6 c3a8b7d0
 *
 * Subkey Generation:
 *   L         = 2c645dcd 72114961 d8b9c864 7aac2c5b
 *   K1        = 58c8bb9a e42292c3 b17390c8 f55858b6
 *   K2        = b1917735 c8452587 62e72191 eab0b16c
 *
 * MAC generation:
 *   C129      = ebd5ccb0 b61ca905 29138303 f3377d22
 *   MACT      = ebd5ccb0
 */
static const uint8_t EIA2_128_K_8[16] = {
        0xb3, 0x12, 0x0f, 0xfd, 0xb2, 0xcf, 0x6a, 0xf4,
        0xe7, 0x3e, 0xaf, 0x2e, 0xf4, 0xeb, 0xec, 0x69
};

static const uint8_t EIA2_128_SK1_8[16] = {
        0x58, 0xc8, 0xbb, 0x9a, 0xe4, 0x22, 0x92, 0xc3,
        0xb1, 0x73, 0x90, 0xc8, 0xf5, 0x58, 0x58, 0xb6
};

static const uint8_t EIA2_128_SK2_8[16] = {
        0xb1, 0x91, 0x77, 0x35, 0xc8, 0x45, 0x25, 0x87,
        0x62, 0xe7, 0x21, 0x91, 0xea, 0xb0, 0xb1, 0x6c
};

static const uint8_t EIA2_128_T_8[4] = {
        0xeb, 0xd5, 0xcc, 0xb0
};

static const uint8_t EIA2_128_M_8[2064] = {
        0x29, 0x6f, 0x39, 0x3c, 0x5c, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0xe0, 0x95, 0x80, 0x45, 0xf3, 0xa0, 0xbb, 0xa4,
        0xe3, 0x96, 0x83, 0x46, 0xf0, 0xa3, 0xb8, 0xa7,
        0xc0, 0x2a, 0x01, 0x8a, 0xe6, 0x40, 0x76, 0x52,
        0x26, 0xb9, 0x87, 0xc9, 0x13, 0xe6, 0xcb, 0xf0,
        0x83, 0x57, 0x00, 0x16, 0xcf, 0x83, 0xef, 0xbc,
        0x61, 0xc0, 0x82, 0x51, 0x3e, 0x21, 0x56, 0x1a,
        0x42, 0x7c, 0x00, 0x9d, 0x28, 0xc2, 0x98, 0xef,
        0xac, 0xe7, 0x8e, 0xd6, 0xd5, 0x6c, 0x2d, 0x45,
        0x05, 0xad, 0x03, 0x2e, 0x9c, 0x04, 0xdc, 0x60,
        0xe7, 0x3a, 0x81, 0x69, 0x6d, 0xa6, 0x65, 0xc6,
        0xc4, 0x86, 0x03, 0xa5, 0x7b, 0x45, 0xab, 0x33,
        0x22, 0x15, 0x85, 0xe6, 0x8e, 0xe3, 0x16, 0x91,
        0x87, 0xfb, 0x02, 0x39, 0x52, 0x86, 0x32, 0xdd,
        0x65, 0x6c, 0x80, 0x7e, 0xa3, 0x24, 0x8b, 0x7b,
        0x46, 0xd0, 0x02, 0xb2, 0xb5, 0xc7, 0x45, 0x8e,
        0xb8, 0x5b, 0x9c, 0xe9, 0x58, 0x79, 0xe0, 0x34,
        0x08, 0x59, 0x05, 0x5e, 0x3b, 0x0a, 0xbb, 0xc3,
        0xea, 0xce, 0x87, 0x19, 0xca, 0xa8, 0x02, 0x65,
        0xc9, 0x72, 0x05, 0xd5, 0xdc, 0x4b, 0xcc, 0x90,
        0x2f, 0xe1, 0x83, 0x96, 0x29, 0xed, 0x71, 0x32,
        0x8a, 0x0f, 0x04, 0x49, 0xf5, 0x88, 0x55, 0x7e,
        0x68, 0x98, 0x86, 0x0e, 0x04, 0x2a, 0xec, 0xd8,
        0x4b, 0x24, 0x04, 0xc2, 0x12, 0xc9, 0x22, 0x2d,
        0xa5, 0xbf, 0x8a, 0x89, 0xef, 0x67, 0x97, 0x87,
        0x0c, 0xf5, 0x07, 0x71, 0xa6, 0x0f, 0x66, 0xa2,
        0xee, 0x62, 0x85, 0x36, 0x57, 0xad, 0xdf, 0x04,
        0xcd, 0xde, 0x07, 0xfa, 0x41, 0x4e, 0x11, 0xf1,
        0x2b, 0x4d, 0x81, 0xb9, 0xb4, 0xe8, 0xac, 0x53,
        0x8e, 0xa3, 0x06, 0x66, 0x68, 0x8d, 0x88, 0x1f,
        0x6c, 0x34, 0x84, 0x21, 0x99, 0x2f, 0x31, 0xb9,
        0x4f, 0x88, 0x06, 0xed, 0x8f, 0xcc, 0xff, 0x4c,
        0x91, 0x23, 0xb8, 0x96, 0x42, 0x52, 0x7a, 0xd6,
        0x13, 0xb1, 0x09, 0xbf, 0x75, 0x16, 0x74, 0x85,
        0xf1, 0x26, 0x8b, 0xf8, 0x84, 0xb4, 0xcd, 0x23,
        0xd2, 0x9a, 0x09, 0x34, 0x92, 0x57, 0x03, 0xd6,
        0x34, 0x09, 0x8f, 0x77, 0x67, 0xf1, 0xbe, 0x74,
        0x91, 0xe7, 0x08, 0xa8, 0xbb, 0x94, 0x9a, 0x38,
        0x73, 0x70, 0x8a, 0xef, 0x4a, 0x36, 0x23, 0x9e,
        0x50, 0xcc, 0x08, 0x23, 0x5c, 0xd5, 0xed, 0x6b,
        0xbe, 0x57, 0x86, 0x68, 0xa1, 0x7b, 0x58, 0xc1,
        0x17, 0x1d, 0x0b, 0x90, 0xe8, 0x13, 0xa9, 0xe4,
        0xf5, 0x8a, 0x89, 0xd7, 0x19, 0xb1, 0x10, 0x42,
        0xd6, 0x36, 0x0b, 0x1b, 0x0f, 0x52, 0xde, 0xb7,
        0x30, 0xa5, 0x8d, 0x58, 0xfa, 0xf4, 0x63, 0x15,
        0x95, 0x4b, 0x0a, 0x87, 0x26, 0x91, 0x47, 0x59,
        0x77, 0xdc, 0x88, 0xc0, 0xd7, 0x33, 0xfe, 0xff,
        0x54, 0x60, 0x0a, 0x0c, 0xc1, 0xd0, 0x30, 0x0a,
        0xaa, 0xeb, 0x94, 0x57, 0x2c, 0x6e, 0x95, 0xb0,
        0x1a, 0xe9, 0x0d, 0xe0, 0x4f, 0x1d, 0xce, 0x47,
        0xf8, 0x7e, 0x8f, 0xa7, 0xbe, 0xbf, 0x77, 0xe1,
        0xdb, 0xc2, 0x0d, 0x6b, 0xa8, 0x5c, 0xb9, 0x14,
        0x3d, 0x51, 0x8b, 0x28, 0x5d, 0xfa, 0x04, 0xb6,
        0x98, 0xbf, 0x0c, 0xf7, 0x81, 0x9f, 0x20, 0xfa,
        0x7a, 0x28, 0x8e, 0xb0, 0x70, 0x3d, 0x99, 0x5c,
        0x59, 0x94, 0x0c, 0x7c, 0x66, 0xde, 0x57, 0xa9,
        0xb7, 0x0f, 0x82, 0x37, 0x9b, 0x70, 0xe2, 0x03,
        0x1e, 0x45, 0x0f, 0xcf, 0xd2, 0x18, 0x13, 0x26,
        0xfc, 0xd2, 0x8d, 0x88, 0x23, 0xba, 0xaa, 0x80,
        0xdf, 0x6e, 0x0f, 0x44, 0x35, 0x59, 0x64, 0x75,
        0x39, 0xfd, 0x89, 0x07, 0xc0, 0xff, 0xd9, 0xd7,
        0x9c, 0x13, 0x0e, 0xd8, 0x1c, 0x9a, 0xfd, 0x9b,
        0x7e, 0x84, 0x8c, 0x9f, 0xed, 0x38, 0x44, 0x3d,
        0x5d, 0x38, 0x0e, 0x53, 0xfb, 0xdb, 0x8a, 0xc8,
        0xc3, 0xd3, 0xf0, 0x68, 0x76, 0x05, 0x4f, 0x12,
        0x24, 0x61, 0x10, 0x7d, 0xe9, 0x2f, 0xea, 0x09,
        0xc6, 0xf6, 0x92, 0x3a, 0x18, 0x8d, 0x53, 0xaf,
        0xe5, 0x4a, 0x10, 0xf6, 0x0e, 0x6e, 0x9d, 0x5a,
        0x03, 0xd9, 0x96, 0xb5, 0xfb, 0xc8, 0x20, 0xf8,
        0xa6, 0x37, 0x11, 0x6a, 0x27, 0xad, 0x04, 0xb4,
        0x44, 0xa0, 0x93, 0x2d, 0xd6, 0x0f, 0xbd, 0x12,
        0x67, 0x1c, 0x11, 0xe1, 0xc0, 0xec, 0x73, 0xe7,
        0x89, 0x87, 0x9f, 0xaa, 0x3d, 0x42, 0xc6, 0x4d,
        0x20, 0xcd, 0x12, 0x52, 0x74, 0x2a, 0x37, 0x68,
        0xc2, 0x5a, 0x90, 0x15, 0x85, 0x88, 0x8e, 0xce,
        0xe1, 0xe6, 0x12, 0xd9, 0x93, 0x6b, 0x40, 0x3b,
        0x07, 0x75, 0x94, 0x9a, 0x66, 0xcd, 0xfd, 0x99,
        0xa2, 0x9b, 0x13, 0x45, 0xba, 0xa8, 0xd9, 0xd5,
        0x40, 0x0c, 0x91, 0x02, 0x4b, 0x0a, 0x60, 0x73,
        0x63, 0xb0, 0x13, 0xce, 0x5d, 0xe9, 0xae, 0x86,
        0x9d, 0x3b, 0x8d, 0x95, 0xb0, 0x57, 0x0b, 0x3c,
        0x2d, 0x39, 0x14, 0x22, 0xd3, 0x24, 0x50, 0xcb,
        0xcf, 0xae, 0x96, 0x65, 0x22, 0x86, 0xe9, 0x6d,
        0xec, 0x12, 0x14, 0xa9, 0x34, 0x65, 0x27, 0x98,
        0x0a, 0x81, 0x92, 0xea, 0xc1, 0xc3, 0x9a, 0x3a,
        0xaf, 0x6f, 0x15, 0x35, 0x1d, 0xa6, 0xbe, 0x76,
        0x4d, 0xf8, 0x97, 0x72, 0xec, 0x04, 0x07, 0xd0,
        0x6e, 0x44, 0x15, 0xbe, 0xfa, 0xe7, 0xc9, 0x25,
        0x80, 0xdf, 0x9b, 0xf5, 0x07, 0x49, 0x7c, 0x8f,
        0x29, 0x95, 0x16, 0x0d, 0x4e, 0x21, 0x8d, 0xaa,
        0xcb, 0x02, 0x94, 0x4a, 0xbf, 0x83, 0x34, 0x0c,
        0xe8, 0xbe, 0x16, 0x86, 0xa9, 0x60, 0xfa, 0xf9,
        0x0e, 0x2d, 0x90, 0xc5, 0x5c, 0xc6, 0x47, 0x5b,
        0xab, 0xc3, 0x17, 0x1a, 0x80, 0xa3, 0x63, 0x17,
        0x49, 0x54, 0x95, 0x5d, 0x71, 0x01, 0xda, 0xb1,
        0x6a, 0xe8, 0x17, 0x91, 0x67, 0xe2, 0x14, 0x44,
        0xb4, 0x43, 0xa9, 0xea, 0xaa, 0x7c, 0x91, 0xde,
        0x36, 0xd1, 0x18, 0xc3, 0x9d, 0x38, 0x9f, 0x8d,
        0xd4, 0x46, 0x9a, 0x84, 0x6c, 0x9a, 0x26, 0x2b,
        0xf7, 0xfa, 0x18, 0x48, 0x7a, 0x79, 0xe8, 0xde,
        0x11, 0x69, 0x9e, 0x0b, 0x8f, 0xdf, 0x55, 0x7c,
        0xb4, 0x87, 0x19, 0xd4, 0x53, 0xba, 0x71, 0x30,
        0x56, 0x10, 0x9b, 0x93, 0xa2, 0x18, 0xc8, 0x96,
        0x75, 0xac, 0x19, 0x5f, 0xb4, 0xfb, 0x06, 0x63,
        0x9b, 0x37, 0x97, 0x14, 0x49, 0x55, 0xb3, 0xc9,
        0x32, 0x7d, 0x1a, 0xec, 0x00, 0x3d, 0x42, 0xec,
        0xd0, 0xea, 0x98, 0xab, 0xf1, 0x9f, 0xfb, 0x4a,
        0xf3, 0x56, 0x1a, 0x67, 0xe7, 0x7c, 0x35, 0xbf,
        0x15, 0xc5, 0x9c, 0x24, 0x12, 0xda, 0x88, 0x1d,
        0xb0, 0x2b, 0x1b, 0xfb, 0xce, 0xbf, 0xac, 0x51,
        0x52, 0xbc, 0x99, 0xbc, 0x3f, 0x1d, 0x15, 0xf7,
        0x71, 0x00, 0x1b, 0x70, 0x29, 0xfe, 0xdb, 0x02,
        0x8f, 0x8b, 0x85, 0x2b, 0xc4, 0x40, 0x7e, 0xb8,
        0x3f, 0x89, 0x1c, 0x9c, 0xa7, 0x33, 0x25, 0x4f,
        0xdd, 0x1e, 0x9e, 0xdb, 0x56, 0x91, 0x9c, 0xe9,
        0xfe, 0xa2, 0x1c, 0x17, 0x40, 0x72, 0x52, 0x1c,
        0x18, 0x31, 0x9a, 0x54, 0xb5, 0xd4, 0xef, 0xbe,
        0xbd, 0xdf, 0x1d, 0x8b, 0x69, 0xb1, 0xcb, 0xf2,
        0x5f, 0x48, 0x9f, 0xcc, 0x98, 0x13, 0x72, 0x54,
        0x7c, 0xf4, 0x1d, 0x00, 0x8e, 0xf0, 0xbc, 0xa1,
        0x92, 0x6f, 0x93, 0x4b, 0x73, 0x5e, 0x09, 0x0b,
        0x3b, 0x25, 0x1e, 0xb3, 0x3a, 0x36, 0xf8, 0x2e,
        0xd9, 0xb2, 0x9c, 0xf4, 0xcb, 0x94, 0x41, 0x88,
        0xfa, 0x0e, 0x1e, 0x38, 0xdd, 0x77, 0x8f, 0x7d,
        0x1c, 0x9d, 0x98, 0x7b, 0x28, 0xd1, 0x32, 0xdf,
        0xb9, 0x73, 0x1f, 0xa4, 0xf4, 0xb4, 0x16, 0x93,
        0x5b, 0xe4, 0x9d, 0xe3, 0x05, 0x16, 0xaf, 0x35,
        0x78, 0x58, 0x1f, 0x2f, 0x13, 0xf5, 0x61, 0xc0,
        0x66, 0x33, 0x61, 0x94, 0x1e, 0xab, 0x24, 0x9a,
        0x4b, 0xc1, 0x23, 0xf8, 0xd1, 0x5c, 0xd7, 0x11,
        0xa9, 0x56, 0xa1, 0xbf, 0x20, 0xfe, 0x6e, 0xb7,
        0x8a, 0xea, 0x23, 0x73, 0x36, 0x1d, 0xa0, 0x42,
        0x6c, 0x79, 0xa5, 0x30, 0xc3, 0xbb, 0x1d, 0xe0,
        0xc9, 0x97, 0x22, 0xef, 0x1f, 0xde, 0x39, 0xac,
        0x2b, 0x00, 0xa0, 0xa8, 0xee, 0x7c, 0x80, 0x0a,
        0x08, 0xbc, 0x22, 0x64, 0xf8, 0x9f, 0x4e, 0xff,
        0xe6, 0x27, 0xac, 0x2f, 0x05, 0x31, 0xfb, 0x55,
        0x4f, 0x6d, 0x21, 0xd7, 0x4c, 0x59, 0x0a, 0x70,
        0xad, 0xfa, 0xa3, 0x90, 0xbd, 0xfb, 0xb3, 0xd6,
        0x8e, 0x46, 0x21, 0x5c, 0xab, 0x18, 0x7d, 0x23,
        0x68, 0xd5, 0xa7, 0x1f, 0x5e, 0xbe, 0xc0, 0x81,
        0xcd, 0x3b, 0x20, 0xc0, 0x82, 0xdb, 0xe4, 0xcd,
        0x2f, 0xac, 0xa2, 0x87, 0x73, 0x79, 0x5d, 0x6b,
        0x0c, 0x10, 0x20, 0x4b, 0x65, 0x9a, 0x93, 0x9e,
        0xf2, 0x9b, 0xbe, 0x10, 0x88, 0x24, 0x36, 0x24,
        0x42, 0x99, 0x27, 0xa7, 0xeb, 0x57, 0x6d, 0xd3,
        0xa0, 0x0e, 0xa5, 0xe0, 0x1a, 0xf5, 0xd4, 0x75,
        0x83, 0xb2, 0x27, 0x2c, 0x0c, 0x16, 0x1a, 0x80,
        0x65, 0x21, 0xa1, 0x6f, 0xf9, 0xb0, 0xa7, 0x22,
        0xc0, 0xcf, 0x26, 0xb0, 0x25, 0xd5, 0x83, 0x6e,
        0x22, 0x58, 0xa4, 0xf7, 0xd4, 0x77, 0x3a, 0xc8,
        0x01, 0xe4, 0x26, 0x3b, 0xc2, 0x94, 0xf4, 0x3d,
        0xef, 0x7f, 0xa8, 0x70, 0x3f, 0x3a, 0x41, 0x97,
        0x46, 0x35, 0x25, 0x88, 0x76, 0x52, 0xb0, 0xb2,
        0xa4, 0xa2, 0xa7, 0xcf, 0x87, 0xf0, 0x09, 0x14,
        0x87, 0x1e, 0x25, 0x03, 0x91, 0x13, 0xc7, 0xe1,
        0x61, 0x8d, 0xa3, 0x40, 0x64, 0xb5, 0x7a, 0x43,
        0xc4, 0x63, 0x24, 0x9f, 0xb8, 0xd0, 0x5e, 0x0f,
        0x26, 0xf4, 0xa6, 0xd8, 0x49, 0x72, 0xe7, 0xa9,
        0x05, 0x48, 0x24, 0x14, 0x5f, 0x91, 0x29, 0x5c,
        0xdb, 0xe3, 0x9a, 0x6f, 0x92, 0x0f, 0xac, 0xc6,
        0x59, 0x71, 0x2b, 0x46, 0xa5, 0x4b, 0xa2, 0x95,
        0xbb, 0xe6, 0xa9, 0x01, 0x54, 0xe9, 0x1b, 0x33,
        0x98, 0x5a, 0x2b, 0xcd, 0x42, 0x0a, 0xd5, 0xc6,
        0x7e, 0xc9, 0xad, 0x8e, 0xb7, 0xac, 0x68, 0x64,
        0xdb, 0x27, 0x2a, 0x51, 0x6b, 0xc9, 0x4c, 0x28,
        0x39, 0xb0, 0xa8, 0x16, 0x9a, 0x6b, 0xf5, 0x8e,
        0x1a, 0x0c, 0x2a, 0xda, 0x8c, 0x88, 0x3b, 0x7b,
        0xf4, 0x97, 0xa4, 0x91, 0x71, 0x26, 0x8e, 0xd1,
        0x5d, 0xdd, 0x29, 0x69, 0x38, 0x4e, 0x7f, 0xf4,
        0xbf, 0x4a, 0xab, 0x2e, 0xc9, 0xec, 0xc6, 0x52,
        0x9c, 0xf6, 0x29, 0xe2, 0xdf, 0x0f, 0x08, 0xa7,
        0x7a, 0x65, 0xaf, 0xa1, 0x2a, 0xa9, 0xb5, 0x05,
        0xdf, 0x8b, 0x28, 0x7e, 0xf6, 0xcc, 0x91, 0x49,
        0x3d, 0x1c, 0xaa, 0x39, 0x07, 0x6e, 0x28, 0xef,
        0x1e, 0xa0, 0x28, 0xf5, 0x11, 0x8d, 0xe6, 0x1a,
        0xe0, 0x2b, 0xb6, 0xae, 0xfc, 0x33, 0x43, 0xa0,
        0x50, 0x29, 0x2f, 0x19, 0x9f, 0x40, 0x18, 0x57,
        0xb2, 0xbe, 0xad, 0x5e, 0x6e, 0xe2, 0xa1, 0xf1,
        0x91, 0x02, 0x2f, 0x92, 0x78, 0x01, 0x6f, 0x04,
        0x77, 0x91, 0xa9, 0xd1, 0x8d, 0xa7, 0xd2, 0xa6,
        0xd2, 0x7f, 0x2e, 0x0e, 0x51, 0xc2, 0xf6, 0xea,
        0x30, 0xe8, 0xac, 0x49, 0xa0, 0x60, 0x4f, 0x4c,
        0x13, 0x54, 0x2e, 0x85, 0xb6, 0x83, 0x81, 0xb9,
        0xfd, 0xcf, 0xa0, 0xce, 0x4b, 0x2d, 0x34, 0x13,
        0x54, 0x85, 0x2d, 0x36, 0x02, 0x45, 0xc5, 0x36,
        0xb6, 0x12, 0xaf, 0x71, 0xf3, 0xe7, 0x7c, 0x90,
        0x95, 0xae, 0x2d, 0xbd, 0xe5, 0x04, 0xb2, 0x65,
        0x73, 0x3d, 0xab, 0xfe, 0x10, 0xa2, 0x0f, 0xc7,
        0xd6, 0xd3, 0x2c, 0x21, 0xcc, 0xc7, 0x2b, 0x8b,
        0x34, 0x44, 0xae, 0x66, 0x3d, 0x65, 0x92, 0x2d,
        0x17, 0xf8, 0x2c, 0xaa, 0x2b, 0x86, 0x5c, 0xd8,
        0x89, 0x13, 0xd2, 0x91, 0xa6, 0x58, 0x99, 0x02,
        0x6e, 0xa1, 0x32, 0x84, 0x39, 0x72, 0x3c, 0x19,
        0x8c, 0x36, 0xb0, 0xc3, 0xc8, 0xd0, 0x85, 0xbf,
        0xaf, 0x8a, 0x32, 0x0f, 0xde, 0x33, 0x4b, 0x4a,
        0x49, 0x19, 0xb4, 0x4c, 0x2b, 0x95, 0xf6, 0xe8,
        0xec, 0xf7, 0x33, 0x93, 0xf7, 0xf0, 0xd2, 0xa4,
        0x0e, 0x60, 0xb1, 0xd4, 0x06, 0x52, 0x6b, 0x02,
        0x2d, 0xdc, 0x33, 0x18, 0x10, 0xb1, 0xa5, 0xf7,
        0xc3, 0x47, 0xbd, 0x53, 0xed, 0x1f, 0x10, 0x5d,
        0x6a, 0x0d, 0x30, 0xab, 0xa4, 0x77, 0xe1, 0x78,
        0x88, 0x9a, 0xb2, 0xec, 0x55, 0xd5, 0x58, 0xde,
        0xab, 0x26, 0x30, 0x20, 0x43, 0x36, 0x96, 0x2b,
        0x4d, 0xb5, 0xb6, 0x63, 0xb6, 0x90, 0x2b, 0x89,
        0xe8, 0x5b, 0x31, 0xbc, 0x6a, 0xf5, 0x0f, 0xc5,
        0x0a, 0xcc, 0xb3, 0xfb, 0x9b, 0x57, 0xb6, 0x63,
        0x29, 0x70, 0x31, 0x37, 0x8d, 0xb4, 0x78, 0x96,
        0xd7, 0xfb, 0xaf, 0x6c, 0x60, 0x0a, 0xdd, 0x2c,
        0x67, 0xf9, 0x36, 0xdb, 0x03, 0x79, 0x86, 0xdb,
        0x85, 0x6e, 0xb4, 0x9c, 0xf2, 0xdb, 0x3f, 0x7d,
        0xa6, 0xd2, 0x36, 0x50, 0xe4, 0x38, 0xf1, 0x88,
        0x40, 0x41, 0xb0, 0x13, 0x11, 0x9e, 0x4c, 0x2a,
        0xe5, 0xaf, 0x37, 0xcc, 0xcd, 0xfb, 0x68, 0x66,
        0x07, 0x38, 0xb5, 0x8b, 0x3c, 0x59, 0xd1, 0xc0,
        0x24, 0x84, 0x37, 0x47, 0x2a, 0xba, 0x1f, 0x35,
        0xca, 0x1f, 0xb9, 0x0c, 0xd7, 0x14, 0xaa, 0x9f,
        0x63, 0x55, 0x34, 0xf4, 0x9e, 0x7c, 0x5b, 0xba,
        0x81, 0xc2, 0xb6, 0xb3, 0x6f, 0xde, 0xe2, 0x1c,
        0xa2, 0x7e, 0x34, 0x7f, 0x79, 0x3d, 0x2c, 0xe9,
        0x44, 0xed, 0xb2, 0x3c, 0x8c, 0x9b, 0x91, 0x4b,
        0xe1, 0x03, 0x35, 0xe3, 0x50, 0xfe, 0xb5, 0x07,
        0x03, 0x94, 0xb7, 0xa4, 0xa1, 0x5c, 0x0c, 0xa1,
        0x20, 0x28, 0x35, 0x68, 0xb7, 0xbf, 0xc2, 0x54,
        0xfe, 0x83, 0x8b, 0x13, 0x7a, 0x21, 0x47, 0xce,
        0x7c, 0x11, 0x3a, 0x3a, 0x4d, 0x65, 0x49, 0x9d,
        0x9e, 0x86, 0xb8, 0x7d, 0xbc, 0xc7, 0xf0, 0x3b,
        0xbd, 0x3a, 0x3a, 0xb1, 0xaa, 0x24, 0x3e, 0xce,
        0x5b, 0xa9, 0xbc, 0xf2, 0x5f, 0x82, 0x83, 0x6c,
        0xfe, 0x47, 0x3b, 0x2d, 0x83, 0xe7, 0xa7, 0x20,
        0x1c, 0xd0, 0xb9, 0x6a, 0x72, 0x45, 0x1e, 0x86,
        0x3f, 0x6c, 0x3b, 0xa6, 0x64, 0xa6, 0xd0, 0x73,
        0xd1, 0xf7, 0xb5, 0xed, 0x99, 0x08, 0x65, 0xd9,
        0x78, 0xbd, 0x38, 0x15, 0xd0, 0x60, 0x94, 0xfc,
        0x9a, 0x2a, 0xba, 0x52, 0x21, 0xc2, 0x2d, 0x5a,
        0xb9, 0x96, 0x38, 0x9e, 0x37, 0x21, 0xe3, 0xaf,
        0x5f, 0x05, 0xbe, 0xdd, 0xc2, 0x87, 0x5e, 0x0d,
        0xfa, 0xeb, 0x39, 0x02, 0x1e, 0xe2, 0x7a, 0x41,
        0x18, 0x7c, 0xbb, 0x45, 0xef, 0x40, 0xc3, 0xe7,
        0x3b, 0xc0, 0x39, 0x89, 0xf9, 0xa3, 0x0d, 0x12,
        0xc5, 0x4b, 0xa7, 0xd2, 0x14, 0x1d, 0xa8, 0xa8,
        0x75, 0x49, 0x3e, 0x65, 0x77, 0x6e, 0xf3, 0x5f,
        0x97, 0xde, 0xbc, 0x22, 0x86, 0xcc, 0x4a, 0xf9,
        0xb4, 0x62, 0x3e, 0xee, 0x90, 0x2f, 0x84, 0x0c,
        0x52, 0xf1, 0xb8, 0xad, 0x65, 0x89, 0x39, 0xae,
        0xf7, 0x1f, 0x3f, 0x72, 0xb9, 0xec, 0x1d, 0xe2,
        0x15, 0x88, 0xbd, 0x35, 0x48, 0x4e, 0xa4, 0x44,
        0x36, 0x34, 0x3f, 0xf9, 0x5e, 0xad, 0x6a, 0xb1,
        0xd8, 0xaf, 0xb1, 0xb2, 0xa3, 0x03, 0xdf, 0x1b,
        0x71, 0xe5, 0x3c, 0x4a, 0xea, 0x6b, 0x2e, 0x3e,
        0x93, 0x72, 0xbe, 0x0d, 0x1b, 0xc9, 0x97, 0x98,
        0xb0, 0xce, 0x3c, 0xc1, 0x0d, 0x2a, 0x59, 0x6d,
        0x56, 0x5d, 0xba, 0x82, 0xf8, 0x8c, 0xe4, 0xcf,
        0xf3, 0xb3, 0x3d, 0x5d, 0x24, 0xe9, 0xc0, 0x83,
        0x11, 0x24, 0xbf, 0x1a, 0xd5, 0x4b, 0x79, 0x25,
        0x32, 0x98, 0x3d, 0xd6, 0xc3, 0xa8, 0xb7, 0xd0
};

/*
 * AES-CMAC-256 vectors
 */

/*
 *  Subkey Generation
 *  K              603DEB10 15CA71BE 2B73AEF0 857D7781
 *                 1F352C07 3B6108D7 2D9810A3 0914DFF4
 *  AES-256(key,0) E568F681 94CF76D6 174D4CC0 4310A854
 *  K1             CAD1ED03 299EEDAC 2E9A9980 8621502F
 *  K2             95A3DA06 533DDB58 5D353301 0C42A0D9
 */
static const uint8_t cmac_256_key[32] = {
        0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
        0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
        0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
        0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4
};
static const uint8_t cmac_256_sub_key1[16] = {
        0xCA, 0xD1, 0xED, 0x03, 0x29, 0x9E, 0xED, 0xAC,
        0x2E, 0x9A, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2F
};
static const uint8_t cmac_256_sub_key2[16] = {
        0x95, 0xA3, 0xDA, 0x06, 0x53, 0x3D, 0xDB, 0x58,
        0x5D, 0x35, 0x33, 0x01, 0x0C, 0x42, 0xA0, 0xD9
};

/*
 *  Example 1: len = 0
 *  M              <empty string>
 *  AES-CMAC       028962F6 1B7BF89E FC6B551F 4667D983
 */
static const uint8_t CMAC_256_T_1[16] = {
        0x02, 0x89, 0x62, 0xF6, 0x1B, 0x7B, 0xF8, 0x9E,
        0xFC, 0x6B, 0x55, 0x1F, 0x46, 0x67, 0xD9, 0x83
};

/*
 *  Example 2: len = 16
 *  M              6BC1BEE2 2E409F96 E93D7E11 7393172A
 *  AES-CMAC       28A7023F 452E8F82 BD4BF28D 8C37C35C
 */
static const uint8_t CMAC_256_T_2[16] = {
        0x28, 0xA7, 0x02, 0x3F, 0x45, 0x2E, 0x8F, 0x82,
        0xBD, 0x4B, 0xF2, 0x8D, 0x8C, 0x37, 0xC3, 0x5C
};

/*
 *  Example 3: len = 20
 *  M              6BC1BEE2 2E409F96 E93D7E11 7393172A
 *                 AE2D8A57
 *  AES-CMAC       156727DC 0878944A 023C1FE0 3BAD6D93
 */
static const uint8_t CMAC_256_T_3[16] = {
        0x15, 0x67, 0x27, 0xDC, 0x08, 0x78, 0x94, 0x4A,
        0x02, 0x3C, 0x1F, 0xE0, 0x3B, 0xAD, 0x6D, 0x93
};

/*
 *  Example 4: len = 64
 *  M              6BC1BEE2 2E409F96 E93D7E11 7393172A
 *                 AE2D8A57 1E03AC9C 9EB76FAC 45AF8E51
 *                 30C81C46 A35CE411 E5FBC119 1A0A52EF
 *                 F69F2445 DF4F9B17 AD2B417B E66C3710
 *  AES-CMAC       E1992190 549F6ED5 696A2C05 6C315410
 */
static const uint8_t CMAC_256_T_4[16] = {
        0xE1, 0x99, 0x21, 0x90, 0x54, 0x9F, 0x6E, 0xD5,
        0x69, 0x6A, 0x2C, 0x05, 0x6C, 0x31, 0x54, 0x10
};


static const struct cmac_rfc4493_vector {
        const uint8_t *key;
        const uint8_t *sub_key1;
        const uint8_t *sub_key2;
        const uint8_t *M;
        size_t len;
        const uint8_t *T;
        size_t T_len;
        enum cmac_type type; /* vector type - std or 3gpp */
} cmac_vectors[] = {
        { key, sub_key1, sub_key2, M, 0,  T_1, 16, CMAC_128 },
        { key, sub_key1, sub_key2, M, 16, T_2, 16, CMAC_128 },
        { key, sub_key1, sub_key2, M, 40, T_3, 16, CMAC_128 },
        { key, sub_key1, sub_key2, M, 64, T_4, 16, CMAC_128 },
        { key, sub_key1, sub_key2, M, 0,  T_1, 15, CMAC_128 },
        { key, sub_key1, sub_key2, M, 16, T_2, 15, CMAC_128 },
        { key, sub_key1, sub_key2, M, 40, T_3, 15, CMAC_128 },
        { key, sub_key1, sub_key2, M, 64, T_4, 15, CMAC_128 },
        { key, sub_key1, sub_key2, M, 0,  T_1, 12, CMAC_128 },
        { key, sub_key1, sub_key2, M, 16, T_2, 12, CMAC_128 },
        { key, sub_key1, sub_key2, M, 40, T_3, 12, CMAC_128 },
        { key, sub_key1, sub_key2, M, 64, T_4, 12, CMAC_128 },
        { key, sub_key1, sub_key2, M, 0,  T_1, 4, CMAC_128 },
        { key, sub_key1, sub_key2, M, 16, T_2, 4, CMAC_128 },
        { key, sub_key1, sub_key2, M, 40, T_3, 4, CMAC_128 },
        { key, sub_key1, sub_key2, M, 64, T_4, 4, CMAC_128 },
        { key, sub_key1, sub_key2, M, 8,  T_5, 16, CMAC_128 },
};

static const struct cmac_rfc4493_vector cmac_256_vectors[] = {
        { cmac_256_key, cmac_256_sub_key1, cmac_256_sub_key2, M, 0,
          CMAC_256_T_1, 16, CMAC_256 },
        { cmac_256_key, cmac_256_sub_key1, cmac_256_sub_key2, M, 16,
          CMAC_256_T_2, 16, CMAC_256 },
        { cmac_256_key, cmac_256_sub_key1, cmac_256_sub_key2, M, 20,
          CMAC_256_T_3, 16, CMAC_256 },
        { cmac_256_key, cmac_256_sub_key1, cmac_256_sub_key2, M, 64,
          CMAC_256_T_4, 16, CMAC_256 },
};

static const struct cmac_rfc4493_vector cmac_3gpp_vectors[] = {
        { EIA2_128_K_1, EIA2_128_SK1_1, EIA2_128_SK2_1,
          EIA2_128_M_1, 122, EIA2_128_T_1, 4, CMAC_128_BITLEN },
        { EIA2_128_K_2, EIA2_128_SK1_2, EIA2_128_SK2_2,
          EIA2_128_M_2, 128, EIA2_128_T_2, 4, CMAC_128_BITLEN },
        { EIA2_128_K_3, EIA2_128_SK1_3, EIA2_128_SK2_3,
          EIA2_128_M_3, 318, EIA2_128_T_3, 4, CMAC_128_BITLEN },
        { EIA2_128_K_4, EIA2_128_SK1_4, EIA2_128_SK2_4,
          EIA2_128_M_4, 575, EIA2_128_T_4, 4, CMAC_128_BITLEN },
        { EIA2_128_K_5, EIA2_128_SK1_5, EIA2_128_SK2_5,
          EIA2_128_M_5, 832, EIA2_128_T_5, 4, CMAC_128_BITLEN },
        { EIA2_128_K_6, EIA2_128_SK1_6, EIA2_128_SK2_6,
          EIA2_128_M_6, 447, EIA2_128_T_6, 4, CMAC_128_BITLEN },
        { EIA2_128_K_7, EIA2_128_SK1_7, EIA2_128_SK2_7,
          EIA2_128_M_7, 2622, EIA2_128_T_7, 4, CMAC_128_BITLEN },
        { EIA2_128_K_8, EIA2_128_SK1_8, EIA2_128_SK2_8,
          EIA2_128_M_8, 16512, EIA2_128_T_8, 4, CMAC_128_BITLEN },
};

static int
cmac_job_ok(const struct cmac_rfc4493_vector *vec,
            const struct IMB_JOB *job,
            const uint8_t *auth,
            const uint8_t *padding,
            const size_t sizeof_padding)
{
        const size_t auth_len = job->auth_tag_output_len_in_bytes;

        if (job->status != IMB_STATUS_COMPLETED) {
                printf("%d Error status:%d", __LINE__, job->status);
                return 0;
        }

        /* hash checks */
        if (memcmp(padding, &auth[sizeof_padding + auth_len],
                   sizeof_padding)) {
                printf("hash overwrite tail\n");
                hexdump(stderr, "Target",
                        &auth[sizeof_padding + auth_len], sizeof_padding);
                return 0;
        }

        if (memcmp(padding, &auth[0], sizeof_padding)) {
                printf("hash overwrite head\n");
                hexdump(stderr, "Target", &auth[0], sizeof_padding);
                return 0;
        }

        if (memcmp(vec->T, &auth[sizeof_padding], auth_len)) {
                printf("hash mismatched\n");
                hexdump(stderr, "Received", &auth[sizeof_padding],
                        auth_len);
                hexdump(stderr, "Expected", vec->T,
                        auth_len);
                return 0;
        }
        return 1;
}

static int
test_cmac(struct IMB_MGR *mb_mgr,
          const struct cmac_rfc4493_vector *vec,
          const int dir,
          const int num_jobs,
          const enum cmac_type type)
{
        DECLARE_ALIGNED(uint32_t expkey[4*15], 16);
        DECLARE_ALIGNED(uint32_t dust[4*15], 16);
        uint32_t skey1[4], skey2[4];
        struct IMB_JOB *job;
        uint8_t padding[16];
        uint8_t **auths = malloc(num_jobs * sizeof(void *));
        int i = 0, jobs_rx = 0, ret = -1;

        if (auths == NULL) {
		fprintf(stderr, "Can't allocate buffer memory\n");
		goto end2;
        }

        memset(padding, -1, sizeof(padding));
        memset(auths, 0, num_jobs * sizeof(void *));

        for (i = 0; i < num_jobs; i++) {
                auths[i] = malloc(16 + (sizeof(padding) * 2));
                if (auths[i] == NULL) {
                        fprintf(stderr, "Can't allocate buffer memory\n");
                        goto end;
                }

                memset(auths[i], -1, 16 + (sizeof(padding) * 2));
        }

        if ((type == CMAC_128) || (type == CMAC_128_BITLEN)) {
                IMB_AES_KEYEXP_128(mb_mgr, vec->key, expkey, dust);
                IMB_AES_CMAC_SUBKEY_GEN_128(mb_mgr, expkey, skey1, skey2);
        } else { /* AES-CMAC-256 */
                IMB_AES_KEYEXP_256(mb_mgr, vec->key, expkey, dust);
                IMB_AES_CMAC_SUBKEY_GEN_256(mb_mgr, expkey, skey1, skey2);
        }

        if (memcmp(vec->sub_key1, skey1, sizeof(skey1))) {
                printf("sub-key1 mismatched\n");
                hexdump(stderr, "Received", &skey1[0], sizeof(skey1));
                hexdump(stderr, "Expected", vec->sub_key1, sizeof(skey1));
		goto end;
        }

        if (memcmp(vec->sub_key2, skey2, sizeof(skey2))) {
                printf("sub-key2 mismatched\n");
                hexdump(stderr, "Received", &skey2[0], sizeof(skey2));
                hexdump(stderr, "Expected", vec->sub_key2, sizeof(skey2));
		goto end;
        }

        while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL)
                ;

        /**
         * Submit all jobs then flush any outstanding jobs
         */
        for (i = 0; i < num_jobs; i++) {
                job = IMB_GET_NEXT_JOB(mb_mgr);
                job->cipher_direction = dir;
                job->chain_order = IMB_ORDER_HASH_CIPHER;
                job->cipher_mode = IMB_CIPHER_NULL;

                switch (type) {
                case CMAC_128:
                        job->hash_alg = IMB_AUTH_AES_CMAC;
                        job->msg_len_to_hash_in_bytes = vec->len;
                        break;
                case CMAC_128_BITLEN:
                        job->hash_alg = IMB_AUTH_AES_CMAC_BITLEN;
                        /* check for std or 3gpp vectors
                           scale len if necessary */
                        if (vec->type == CMAC_128)
                                job->msg_len_to_hash_in_bits = vec->len * 8;
                        else
                                job->msg_len_to_hash_in_bits = vec->len;
                        break;
                case CMAC_256:
                        job->hash_alg = IMB_AUTH_AES_CMAC_256;
                        job->msg_len_to_hash_in_bytes = vec->len;
                        break;
                default:
                        printf("Invalid CMAC type specified\n");
                        goto end;
                }
                job->u.CMAC._key_expanded = expkey;
                job->u.CMAC._skey1 = skey1;
                job->u.CMAC._skey2 = skey2;
                job->src = vec->M;
                job->hash_start_src_offset_in_bytes = 0;
                job->auth_tag_output = auths[i] + sizeof(padding);
                job->auth_tag_output_len_in_bytes = vec->T_len;

                job->user_data = auths[i];

                job = IMB_SUBMIT_JOB(mb_mgr);
                if (job) {
                        jobs_rx++;
                        if (num_jobs < 4) {
                                printf("%d Unexpected return from submit_job\n",
                                       __LINE__);
                                goto end;
                        }
                        if (!cmac_job_ok(vec, job, job->user_data, padding,
                                         sizeof(padding)))
                                goto end;
                }
        }

        while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL) {
                jobs_rx++;

                if (!cmac_job_ok(vec, job, job->user_data, padding,
                                 sizeof(padding)))
                        goto end;
        }

        if (jobs_rx != num_jobs) {
                printf("Expected %d jobs, received %d\n", num_jobs, jobs_rx);
                goto end;
        }

        /**
         * Submit each job and flush immediately
         */
        for (i = 0; i < num_jobs; i++) {
                struct IMB_JOB *first_job = NULL;

                job = IMB_GET_NEXT_JOB(mb_mgr);
                first_job = job;

                job->cipher_direction = dir;
                job->chain_order = IMB_ORDER_HASH_CIPHER;
                job->cipher_mode = IMB_CIPHER_NULL;

                switch (type) {
                case CMAC_128:
                        job->hash_alg = IMB_AUTH_AES_CMAC;
                        job->msg_len_to_hash_in_bytes = vec->len;
                        break;
                case CMAC_128_BITLEN:
                        job->hash_alg = IMB_AUTH_AES_CMAC_BITLEN;
                        /* check for std or 3gpp vectors
                           scale len if necessary */
                        if (vec->type == CMAC_128)
                                job->msg_len_to_hash_in_bits = vec->len * 8;
                        else
                                job->msg_len_to_hash_in_bits = vec->len;
                        break;
                case CMAC_256:
                        job->hash_alg = IMB_AUTH_AES_CMAC_256;
                        job->msg_len_to_hash_in_bytes = vec->len;
                        break;
                default:
                        printf("Invalid CMAC type specified\n");
                        goto end;
                }
                job->u.CMAC._key_expanded = expkey;
                job->u.CMAC._skey1 = skey1;
                job->u.CMAC._skey2 = skey2;
                job->src = vec->M;
                job->hash_start_src_offset_in_bytes = 0;
                job->auth_tag_output = auths[i] + sizeof(padding);
                job->auth_tag_output_len_in_bytes = vec->T_len;

                job->user_data = auths[i];

                job = IMB_SUBMIT_JOB(mb_mgr);
                if (job != NULL) {
                        printf("Received job, expected NULL\n");
                        goto end;
                }

                while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL) {
                        if (job != first_job) {
                                printf("Invalid return job received\n");
                                goto end;
                        }
                        if (!cmac_job_ok(vec, job, job->user_data, padding,
                                         sizeof(padding)))
                                goto end;
                }
        }

        ret = 0;

 end:
        while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL)
                ;

        for (i = 0; i < num_jobs; i++) {
                if (auths[i] != NULL)
                        free(auths[i]);
        }

 end2:
        if (auths != NULL)
                free(auths);

        return ret;
}

static void
test_cmac_std_vectors(struct IMB_MGR *mb_mgr,
                      struct test_suite_context *ctx,
                      const int num_jobs)
{
	const int vectors_cnt = DIM(cmac_vectors);
	int vect;

	printf("AES-CMAC-128 standard test vectors (N jobs = %d):\n", num_jobs);
	for (vect = 1; vect <= vectors_cnt; vect++) {
                const int idx = vect - 1;
#ifdef DEBUG
		printf("Standard CMAC-128 vector [%d/%d] M len: %d, T len:%d\n",
                       vect, vectors_cnt,
                       (int) cmac_vectors[idx].len,
                       (int) cmac_vectors[idx].T_len);
#else
		printf(".");
#endif

                if (test_cmac(mb_mgr, &cmac_vectors[idx],
                              IMB_DIR_ENCRYPT, num_jobs, CMAC_128)) {
                        printf("error #%d encrypt\n", vect);
                        test_suite_update(ctx, 0, 1);
                } else {
                        test_suite_update(ctx, 1, 0);
                }

                if (test_cmac(mb_mgr, &cmac_vectors[idx],
                              IMB_DIR_DECRYPT, num_jobs, CMAC_128)) {
                        printf("error #%d decrypt\n", vect);
                        test_suite_update(ctx, 0, 1);
                } else {
                        test_suite_update(ctx, 1, 0);
                }
	}
	printf("\n");
}

static void
test_cmac_256_std_vectors(struct IMB_MGR *mb_mgr,
                          struct test_suite_context *ctx,
                          const int num_jobs)
{
	const int vectors_cnt = DIM(cmac_256_vectors);
	int vect;

	printf("AES-CMAC-256 standard test vectors (N jobs = %d):\n", num_jobs);
	for (vect = 1; vect <= vectors_cnt; vect++) {
                const int idx = vect - 1;
#ifdef DEBUG
		printf("Standard CMAC-256 vector [%d/%d] M len: %d, T len:%d\n",
                       vect, vectors_cnt,
                       (int) cmac_256_vectors[idx].len,
                       (int) cmac_256_vectors[idx].T_len);
#else
		printf(".");
#endif

                if (test_cmac(mb_mgr, &cmac_256_vectors[idx],
                              IMB_DIR_ENCRYPT, num_jobs, CMAC_256)) {
                        printf("error #%d encrypt\n", vect);
                        test_suite_update(ctx, 0, 1);
                } else {
                        test_suite_update(ctx, 1, 0);
                }
                if (test_cmac(mb_mgr, &cmac_256_vectors[idx],
                              IMB_DIR_DECRYPT, num_jobs, CMAC_256)) {
                        printf("error #%d decrypt\n", vect);
                        test_suite_update(ctx, 0, 1);
                } else {
                        test_suite_update(ctx, 1, 0);
                }
	}
	printf("\n");
}

static void
test_cmac_bitlen_std_vectors(struct IMB_MGR *mb_mgr,
                             struct test_suite_context *ctx,
                             const int num_jobs)
{
	const int vectors_cnt = sizeof(cmac_vectors) / sizeof(cmac_vectors[0]);
	int vect;

        printf("AES-CMAC-128 BITLEN standard test vectors "
               "(N jobs = %d):\n", num_jobs);
	for (vect = 1; vect <= vectors_cnt; vect++) {
                const int idx = vect - 1;
#ifdef DEBUG
		printf("Standard vector [%d/%d] M len: %d (bits), "
                       "T len:%d\n",
                       vect, vectors_cnt,
                       (int) cmac_vectors[idx].len * 8,
                       (int) cmac_vectors[idx].T_len);
#else
		printf(".");
#endif

                if (test_cmac(mb_mgr, &cmac_vectors[idx],
                              IMB_DIR_ENCRYPT, num_jobs, CMAC_128_BITLEN)) {
                        printf("error #%d encrypt\n", vect);
                        test_suite_update(ctx, 0, 1);
                } else {
                        test_suite_update(ctx, 1, 0);
                }

                if (test_cmac(mb_mgr, &cmac_vectors[idx],
                              IMB_DIR_DECRYPT, num_jobs, CMAC_128_BITLEN)) {
                        printf("error #%d decrypt\n", vect);
                        test_suite_update(ctx, 0, 1);
                } else {
                        test_suite_update(ctx, 1, 0);
                }

	}
        printf("\n");
}

static void
test_cmac_bitlen_3gpp_vectors(struct IMB_MGR *mb_mgr,
                              struct test_suite_context *ctx,
                              const int num_jobs)
{
	const int vectors_cnt =
                sizeof(cmac_3gpp_vectors) / sizeof(cmac_3gpp_vectors[0]);
	int vect;

	printf("AES-CMAC-128 BITLEN 3GPP test vectors (N jobs = %d):\n",
               num_jobs);
	for (vect = 1; vect <= vectors_cnt; vect++) {
                const int idx = vect - 1;
#ifdef DEBUG
		printf("3GPP vector [%d/%d] M len: %d (bits), "
                       "T len:%d (bytes)\n",
                       vect, vectors_cnt,
                       (int) cmac_3gpp_vectors[idx].len,
                       (int) cmac_3gpp_vectors[idx].T_len);
#else
		printf(".");
#endif

                if (test_cmac(mb_mgr, &cmac_3gpp_vectors[idx],
                              IMB_DIR_ENCRYPT, num_jobs, CMAC_128_BITLEN)) {
                        printf("error #%d encrypt\n", vect);
                        test_suite_update(ctx, 0, 1);
                } else {
                        test_suite_update(ctx, 1, 0);
                }

                if (test_cmac(mb_mgr, &cmac_3gpp_vectors[idx],
                              IMB_DIR_DECRYPT, num_jobs, CMAC_128_BITLEN)) {
                        printf("error #%d decrypt\n", vect);
                        test_suite_update(ctx, 0, 1);
                } else {
                        test_suite_update(ctx, 1, 0);
                }

	}
	printf("\n");
}

int
cmac_test(struct IMB_MGR *mb_mgr)
{
        int i, errors = 0;
        struct test_suite_context ctx;

        /* CMAC 128 with standard vectors */
        test_suite_start(&ctx, "AES-CMAC-128");
        for (i = 1; i < 20; i++)
                test_cmac_std_vectors(mb_mgr, &ctx, i);
        errors += test_suite_end(&ctx);

        /* CMAC 128 BITLEN with standard vectors */
        test_suite_start(&ctx, "AES-CMAC-128-BIT-LENGTH");
        for (i = 1; i < 20; i++)
                test_cmac_bitlen_std_vectors(mb_mgr, &ctx, i);

        /* CMAC 128 BITLEN with 3GPP vectors */
        for (i = 1; i < 20; i++)
                test_cmac_bitlen_3gpp_vectors(mb_mgr, &ctx, i);
        errors += test_suite_end(&ctx);

        /* CMAC 256 with standard vectors */
        test_suite_start(&ctx, "AES-CMAC-256");
        for (i = 1; i < 20; i++)
                test_cmac_256_std_vectors(mb_mgr, &ctx, i);
        errors += test_suite_end(&ctx);

	return errors;
}
